/**
 * Copyright 2021 Huawei Technologies Co., Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @addtogroup MindSpore
 * @{
 *
 * @brief 提供MindSpore Lite的模型推理相关接口，该模块下的接口是非线程安全的。
 * 
 * @syscap SystemCapability.Ai.MindSpore
 * @since 9
 */

/**
 * @file context.h
 * @kit MindSporeLiteKit
 * @brief 提供了Context相关的接口，可以配置运行时信息，该接口是非线程安全的。
 *
 * @include <mindspore/context.h>
 * @library libmindspore_lite_ndk.so
 * @syscap SystemCapability.Ai.MindSpore
 * @since 9
 */
#ifndef MINDSPORE_INCLUDE_C_API_CONTEXT_C_H
#define MINDSPORE_INCLUDE_C_API_CONTEXT_C_H

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "mindspore/types.h"
#include "mindspore/status.h"

#ifdef __cplusplus
extern "C"
{
#endif
/**
 * @brief MindSpore Lite的上下文信息的指针，该指针会指向Context。
 *
 * @since 9
 */
typedef void *OH_AI_ContextHandle;

/**
 * @brief MindSpore Lite的运行设备信息的指针。
 *
 * @since 9
 */
typedef void *OH_AI_DeviceInfoHandle;

/**
 * @brief 创建一个上下文的对象。注意：此接口需跟OH_AI_ContextDestroy配套使用。
 *
 * @return 指向上下文信息的{@link OH_AI_ContextHandle}。
 * @since 9
 */
OH_AI_API OH_AI_ContextHandle OH_AI_ContextCreate();

/**
 * @brief 释放上下文对象。
 *
 * @param context 指向{@link OH_AI_ContextHandle}的二级指针，上下文销毁后会对context置为空指针。
 * @since 9
 */
OH_AI_API void OH_AI_ContextDestroy(OH_AI_ContextHandle *context);

/**
 * @brief 设置运行时的线程数量。
 *
 * @param context 指向上下文信息实例的{@link OH_AI_ContextHandle}。
 * @param thread_num 运行时的线程数量。长度跟随系统限制。
 * @since 9
 */
OH_AI_API void OH_AI_ContextSetThreadNum(OH_AI_ContextHandle context, int32_t thread_num);

/**
 * @brief 获取线程数量。
 *
 * @param context 指向上下文信息实例的{@link OH_AI_ContextHandle}。
 * @return 当前的线程数量。
 * @since 9
 */
OH_AI_API int32_t OH_AI_ContextGetThreadNum(const OH_AI_ContextHandle context);

/**
 * @brief 设置运行时线程绑定CPU核心的策略，按照CPU物理核频率分为大、中、小三种类型的核心，并且仅需绑大核或者绑中核，不需要绑小核。
 *
 * @param context 指向上下文信息实例的{@link OH_AI_ContextHandle}。
 * @param mode 绑核策略。一共有三种策略，0为不绑核，1为大核优先，2为中核优先。
 * @since 9
 */
OH_AI_API void OH_AI_ContextSetThreadAffinityMode(OH_AI_ContextHandle context, int mode);

/**
 * @brief 获取运行时线程绑定CPU核心的策略。
 *
 * @param context 指向上下文信息实例的{@link OH_AI_ContextHandle}。
 * @return 绑核策略。一共有三种策略，0为不绑核，1为大核优先，2为中核优先。
 * @since 9
 */
OH_AI_API int OH_AI_ContextGetThreadAffinityMode(const OH_AI_ContextHandle context);

/**
 * @brief 设置运行时线程绑定CPU核心的列表。\n
 * 
 * 例如：当core_list=[2,6,8]时，则线程会在CPU的第2，6，8个核心上运行。\n
 * 如果对于同一个上下文对象，调用了{@link OH_AI_ContextSetThreadAffinityMode}和{@link OH_AI_ContextSetThreadAffinityCoreList}。\n
 * 这两个函数，则仅{@link OH_AI_ContextSetThreadAffinityCoreList}的core_list参数生效，而{@link OH_AI_ContextSetThreadAffinityMode}的mode参数不生效。
 * 
 * @param context 指向上下文信息实例的{@link OH_AI_ContextHandle}。
 * @param core_list CPU绑核的列表。
 * @param core_num 核的数量，它就代表{@link core_list}的长度。
 * @since 9
 */
OH_AI_API void OH_AI_ContextSetThreadAffinityCoreList(OH_AI_ContextHandle context, const int32_t *core_list,
                                                        size_t core_num);

/**
 * @brief 获取CPU绑核列表。
 *
 * @param context 指向上下文信息实例的{@link OH_AI_ContextHandle}。
 * @param core_num 该参数是输出参数，表示核的数量。
 * @return CPU绑核列表。此列表对象由{@link OH_AI_ContextHandle}管理，调用者无须手动释放。
 * @since 9
 */
OH_AI_API const int32_t *OH_AI_ContextGetThreadAffinityCoreList(const OH_AI_ContextHandle context, size_t *core_num);

/**
 * @brief 设置运行时是否支持并行。此接口特性当前未开启，设置无效。
 *
 * @param context 指向上下文信息实例的{@link OH_AI_ContextHandle}。
 * @param is_parallel 是否支持并行。true为支持并行，false为不支持并行。
 * @since 9
 */
OH_AI_API void OH_AI_ContextSetEnableParallel(OH_AI_ContextHandle context, bool is_parallel);

/**
 * @brief 获取是否支持算子间并行。
 *
 * @param context 指向上下文信息实例的{@link OH_AI_ContextHandle}。
 * @return 是否支持并行。true为支持并行，false为不支持并行。
 * @since 9
 */
OH_AI_API bool OH_AI_ContextGetEnableParallel(const OH_AI_ContextHandle context);

/**
 * @brief 将一个用户定义的运行设备信息附加到推理上下文中。
 *
 * @param context 指向上下文信息实例的{@link OH_AI_ContextHandle}。
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @since 9
 */
OH_AI_API void OH_AI_ContextAddDeviceInfo(OH_AI_ContextHandle context, OH_AI_DeviceInfoHandle device_info);

/**
 * @brief 创建一个设备信息对象。
 *
 * @param device_type 设备类型，具体见{@link OH_AI_DeviceType}。
 * @return 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @since 9
 */
OH_AI_API OH_AI_DeviceInfoHandle OH_AI_DeviceInfoCreate(OH_AI_DeviceType device_type);

/**
 * @brief 释放设备信息实例。注意：设备信息实例被添加到context后，无须调用者手动释放。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @since 9
 */
OH_AI_API void OH_AI_DeviceInfoDestroy(OH_AI_DeviceInfoHandle *device_info);

/**
 * @brief 设置生产商的名称。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @param provider 生产商的名称。字符串长度跟随系统限制。
 * @since 9
 */
OH_AI_API void OH_AI_DeviceInfoSetProvider(OH_AI_DeviceInfoHandle device_info, const char *provider);

/**
 * @brief 获取生产商的名称。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @return 生产商的名称。
 * @since 9
 */
OH_AI_API const char *OH_AI_DeviceInfoGetProvider(const OH_AI_DeviceInfoHandle device_info);

/**
 * @brief 设置生产商设备的名称。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @param device 生产商设备名称。例如: CPU。字符串长度跟随系统限制。
 * @since 9
 */
OH_AI_API void OH_AI_DeviceInfoSetProviderDevice(OH_AI_DeviceInfoHandle device_info, const char *device);

/**
 * @brief 获取生产商设备的名称。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @return 生产商设备的名称。
 * @since 9
 */
OH_AI_API const char *OH_AI_DeviceInfoGetProviderDevice(const OH_AI_DeviceInfoHandle device_info);

/**
 * @brief 获取设备的类型。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @return 生产商设备类型。
 * @since 9
 */
OH_AI_API OH_AI_DeviceType OH_AI_DeviceInfoGetDeviceType(const OH_AI_DeviceInfoHandle device_info);

/**
 * @brief 设置是否开启float16推理模式，仅CPU/GPU设备可用。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @param is_fp16 是否开启float16推理模式。true为开启float16推理模式，false为不开启float16推理模式。
 * @since 9
 */
OH_AI_API void OH_AI_DeviceInfoSetEnableFP16(OH_AI_DeviceInfoHandle device_info, bool is_fp16);

/**
 * @brief 获取是否开启float16推理模式，仅CPU/GPU设备可用。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @return 设置是否开启float16推理模式。true为开启float16推理模式，false为不开启float16推理模式。
 * @since 9
 */
OH_AI_API bool OH_AI_DeviceInfoGetEnableFP16(const OH_AI_DeviceInfoHandle device_info);

/**
 * @brief 设置NPU的频率，仅NPU设备可用。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @param frequency 频率类型，取值范围为0-4，默认是3。0表示不设置，由系统调节；1表示低功耗；2表示平衡；3表示高性能；4表示超高性能。
 * @since 9
 */
OH_AI_API void OH_AI_DeviceInfoSetFrequency(OH_AI_DeviceInfoHandle device_info, int frequency);

/**
 * @brief 获取NPU的频率类型，仅NPU设备可用。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @return NPU的频率类型。取值范围为0-4，0表示不设置，由系统调节；1表示低功耗；2表示平衡；3表示高性能；4表示超高性能。
 * @since 9
 */
OH_AI_API int OH_AI_DeviceInfoGetFrequency(const OH_AI_DeviceInfoHandle device_info);

/**
 * @brief 获取系统中所有NNRt硬件设备的描述信息。
 *
 * @param num 输出参数，返回设备数量。
 * @return 指向NNRt设备描述信息实例数组的指针。当获取失败时，返回NULL。
 * @since 10
 */
OH_AI_API NNRTDeviceDesc *OH_AI_GetAllNNRTDeviceDescs(size_t *num);

/**
 * @brief 获取NNRt设备描述信息数组中的元素指针。
 *
 * @param descs NNRt设备描述信息数组。
 * @param index 数组元素索引。
 * @return NNRt设备描述信息类型指针。
 * @since 10
 */
OH_AI_API NNRTDeviceDesc *OH_AI_GetElementOfNNRTDeviceDescs(NNRTDeviceDesc *descs, size_t index);

/**
 * @brief 销毁从{@link OH_AI_GetAllNNRTDeviceDescs}获取的NNRt描写信息实例数组。
 *
 * @param desc 指向NNRt设备描述信息实例数组的二重指针。销毁结束，desc指向内容会被置为NULL。
 * @since 10
 */
OH_AI_API void OH_AI_DestroyAllNNRTDeviceDescs(NNRTDeviceDesc **desc);

/**
 * @brief 从特定的NNRt设备描述信息实例获取NNRt设备ID。注意，此ID只对NNRt有效。
 *
 * @param desc 指向NNRt设备描述信息实例的指针。
 * @return NNRt设备ID。
 * @since 10
 */
OH_AI_API size_t OH_AI_GetDeviceIdFromNNRTDeviceDesc(const NNRTDeviceDesc *desc);

/**
 * @brief 从特定的NNRt设备描述信息实例获取NNRt设备名称。
 *
 * @param desc 指向NNRt设备描述信息实例的指针。
 * @return NNRt设备名称，指向一个常量字符串的指针，该常量字符串由desc持有，调用者无需单独释放此指针。
 * @since 10
 */
OH_AI_API const char *OH_AI_GetNameFromNNRTDeviceDesc(const NNRTDeviceDesc *desc);

/**
 * @brief 从特定的NNRt设备描述信息实例获取NNRt设备类型。
 *
 * @param desc 指向NNRt设备描述信息实例的指针。
 * @return {@link OH_AI_NNRTDeviceType} NNRt设备类型。
 * @since 10
 */
OH_AI_API OH_AI_NNRTDeviceType OH_AI_GetTypeFromNNRTDeviceDesc(const NNRTDeviceDesc *desc);

/**
 * @brief 查找指定名称的NNRt设备，根据找到的第一个设备信息，创建NNRt设备信息。
 *
 * @param name 目标NNRt设备名。字符串长度跟随系统限制。
 * @return 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @since 10
 */
OH_AI_API OH_AI_DeviceInfoHandle OH_AI_CreateNNRTDeviceInfoByName(const char *name);

/**
 * @brief 查找指定类型的NNRt设备，根据找到的第一个设备信息，创建NNRt设备信息。
 *
 * @param type {@link OH_AI_NNRTDeviceType} 目标NNRt设备类型。
 * @return 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @since 10
 */
OH_AI_API OH_AI_DeviceInfoHandle OH_AI_CreateNNRTDeviceInfoByType(OH_AI_NNRTDeviceType type);

/**
 * @brief 设置NNRt设备ID，仅NNRt设备可用。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @param device_id NNRt设备ID。
 * @since 10
 */
OH_AI_API void OH_AI_DeviceInfoSetDeviceId(OH_AI_DeviceInfoHandle device_info, size_t device_id);

/**
 * @brief 获取NNRt设备ID，仅NNRt设备可用。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @return NNRt设备ID。
 * @since 10
 */
OH_AI_API size_t OH_AI_DeviceInfoGetDeviceId(const OH_AI_DeviceInfoHandle device_info);

/**
 * @brief 设置NNRt性能模式，仅NNRt设备可用。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @param mode {@link OH_AI_PerformanceMode} NNRt性能模式。
 * @since 10
 */
OH_AI_API void OH_AI_DeviceInfoSetPerformanceMode(OH_AI_DeviceInfoHandle device_info, OH_AI_PerformanceMode mode);

/**
 * @brief 获取NNRt性能模式，仅NNRt设备可用。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @return {@link OH_AI_PerformanceMode} NNRt性能模式。
 * @since 10
 */
OH_AI_API OH_AI_PerformanceMode OH_AI_DeviceInfoGetPerformanceMode(const OH_AI_DeviceInfoHandle device_info);


/**
 * @brief 设置NNRt任务优先级，仅NNRt设备可用。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @param priority {@link OH_AI_Priority} NNRt任务优先级。
 * @since 10
 */
OH_AI_API void OH_AI_DeviceInfoSetPriority(OH_AI_DeviceInfoHandle device_info, OH_AI_Priority priority);

/**
 * @brief 获取NNRt任务优先级，仅NNRt设备可用。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @return {@link OH_AI_Priority} NNRt任务优先级。
 * @since 10
 */
OH_AI_API OH_AI_Priority OH_AI_DeviceInfoGetPriority(const OH_AI_DeviceInfoHandle device_info);

/**
 * @brief 向设备信息中添加键/值对形式的扩展配置。只对NNRt设备信息有效。\n
 *
 * 当前仅支持配置以下11种键：{"CachePath": "YourCachePath"}，{"CacheVersion": "YourCacheVersion"}，\n
 * {"QuantBuffer": "YourQuantBuffer"}，{"ModelName": "YourModelName"}，\n
 * {"isProfiling": "YourProfilingSwitch"}，{"opLayout": "YourOpLayout"}，\n
 * {"InputDims": "YourInputDims"}，{"DynamicDims": "YourDynamicDims"}，\n
 * {"QuantConfigData": "YourQuantConfigData"}，{"BandMode": "YourBandMode"}，\n
 * {"NPU_FM_SHARED": "YourNPU_FM_SHARED"}，用户可根据使用情况配置各个键对应的值。
 *
 * @param device_info 指向设备信息实例的{@link OH_AI_DeviceInfoHandle}。
 * @param name 单个扩展项的键，格式为C字符串。字符串长度限制为128。
 * @param value 单个扩展项的值内容首地址。字符串长度跟随系统限制。
 * @param value_size 单个扩展项的值内容长度。
 * @return {@link OH_AI_Status} 执行状态码，若成功返回OH_AI_STATUS_SUCCESS，失败则返回具体错误码。
 * @since 10
 */
OH_AI_API OH_AI_Status OH_AI_DeviceInfoAddExtension(OH_AI_DeviceInfoHandle device_info, const char *name,
    const char *value, size_t value_size);
#ifdef __cplusplus
}
#endif

/** @} */
#endif // MINDSPORE_INCLUDE_C_API_CONTEXT_C_H
